(ns clojure-demo.lifes2
  :use [clojure.pprint])

#_(defn window
    "Returns a lazy sequence of 3-item windows centered around each item of coll."
    [coll]
    (partition 3 1 (concat [nil] coll [nil])))	     ;先在coll前后添加一个nil元素。

#_(defn cell-block
    "Creates a sequences of 3x3 windows from a triple of 3 sequences."
    [[left mid right]]
    (window (map vector
                 (or left (repeat nil)) mid (or right (repeat nil)))))

;;;;;;;;;;;;;;
;窗口函数
(defn window
    "Returns a lazy sequence of 3-item windows centered around each item of coll, padded as necessary with pad or nil."
    (   [coll] (window nil coll))
    (   [pad coll]      ;coll是一个3元素的向量，它的元素也是序列。
        (partition 3 1 (concat [pad] coll [pad]))))    ;先在coll前后各添加[pad]元素（注意[]，所以不是添加pad里面的元素）。

;?邻居块函数，将二维数组切成一系列的邻居块。
(defn cell-block
    "Creates a sequences of 3x3 windows from a triple of 3 sequences."
    [[left mid right]]  ;left，mid，right都是序列。
    (window (map vector left mid right)))   ;将left，mid，right都转成向量。

;计算“给定邻居块的中心细胞”在下一轮中的状态。

(defn liveness
    "Returns the liveness (nil or :on) of the center cell for the next step."
    [block]     ;3*3的块。
    (let [[_ [_ center _] _] block]
         (case (- (count (filter #{:on} (apply concat block)))  ;块中的活格子数。
                  (if (= :on center) 1 0))  ;中心格子的当前状态如果为存活，返回1，否则0。
;排除中心格子后，得到块的中心格子的活邻居数。

               2 center     ;两个活邻居，维持原状态。
               3 :on
               nil)))

(defn- step-row
    "Yields the next state of the center row."
    [rows-triple]
    (vec (map liveness (cell-block rows-triple))))

;----
;繁衍函数，得到下一代细胞图，不再依赖下标。

(defn index-free-step
    "Yields the next state of the board."
    [board]
    (vec (map step-row (window (repeat nil) board))))

;;;;;;;;;;;;;;;
;生成细胞图（二维向量）。
(defn empty-board
    "Creates a rectangular empty board of the specified width and height."
    [w h]
    (vec (repeat w (vec (repeat h nil)))))

;--
;初始化细胞图。
(defn populate
    "Turns :on each of the cells specified as [y, x] coordinates."
    [board living-cells]   ;living-cells，活格子的坐标
    (reduce (fn [board coordinates]
                (assoc-in board coordinates :on))
            board
            living-cells))

(def glider (populate (empty-board 6 6) #{[2 0] [2 1] [2 2] [1 2] [0 1]}))

(pprint glider)

(index-free-step glider)
;[  [nil nil nil nil nil nil] 
;   [:on nil :on nil nil nil] 
;   [nil :on :on nil nil nil] 
;   [nil :on nil nil nil nil] 
;   [nil nil nil nil nil nil] 
;   [nil nil nil nil nil nil]]